rm(list = ls(all = TRUE))
setwd("C:\\Users\\lenovo\\Desktop\\R\\神经网络_R语言实现")
#1.1 简介
#AI（artificial intelligenice）、ML（machine learning）与DL（deep learning）

#1.2 神经网络的灵感
#神经元
#大规模并行计算、分布式表达和计算、学习和泛化能力、容错、低能耗

#1.3 神经网络的工作原理
#输入层、隐含层、输出层、权重、偏差、激活函数
#神经元的输出是输入的加权和加上偏差的函数

#1.4 分层方法
#输入层、隐含层（中间层）、输出层

#1.5 权重与偏差
#outputs = sum（weights*inputs）+ bias

#1.6 训练神经网络
#向模型呈现样本数据并修改权重以更好地近似所需函数
#1.6.1 有监督学习
#为神经网络提供输入和所需的输出；度量网络对输入的响应

#1.6.2 无监督学习
#只提供输入，神经网络调整自己的权重，使类似的输入产生类似的输出

#1.7 epoch
#一次迭代或完成网络输入和更新网络权重的过程称为epoch
#它是一次完整的前向和反向传播，用于更新权重
#是对整个数据集的完整阅读
#有时需要数万次的epoch才能有效地训练神经网络

#1.8 激活函数
#神经网络的处理过程
#将输入转换为输出的数学函数，并提升神经网络的处理能力
#激活函数赋予神经网络非线性的特性，使其成为真正的通用函数逼近器

#1.9 不同的激活函数
#1.9.1 线性函数
#最简单、最基本的线性函数
#1.9.2 单位阶梯激活函数
#输出本质上是二值的
#1.9.3 Sigmoid函数
#最早的也是最常使用的激活函数，用于将输入压缩为0-1之间的任何值
#1.9.4 双曲正切函数
#一个缩放的Sigmoid函数，但是导数更陡峭、梯度更大
#y = tanh（x）
#1.9.5 线性修正单元函数（Rectified Linear Unit，ReLU)
#2015年以来使用最多的激活函数
#f（x） = 0 (x<0>); 1 (x>=0)

#1.10 使用哪些激活函数
#必须具有以下几点才具有鲁棒性
#应该是可导的。（反向传播）；激活函数不应该导致梯度消失
#处理应该简单快捷
#不应该以0为中心

#ReLU函数为神经网络、DL问题的首选函数
#ReLU函数用于隐含层
#在输出层中，对于逻辑问题用softmax函数；回归问题首用线性函数

#1.11 感知机和多层架构
#感知机是将一组输入分为两类（1、-1）的单个神经元
#输入为网格：用于识别视觉图像的形状
#通常使用阶跃函数，输入的 加权和 超过阈值，输出1；否则为0

#感知机层组合在一起，形成多层架构
#多层感知机（MLP）为神经网络中应用最为广泛的架构

#1.12 前向和反向传播
#从输入层到隐含层，再到输出层的处理称为前向传播（forward propagation）
#在每层施加sum（输入*权重）+偏差
#大量的隐含层造就深度神经网络

#到达输出层，计算误差：预测输出减去原始输出
#该误差用来纠正前向传播中使用的权重和偏差：使用倒数函数
#必须改变的权重由梯度下降（gradient descent）决定

#反向传播过程使用每个神经元的激活函数的偏导数
#来识别每个进入权重的方向上的斜率（或梯度）
#梯度用于表明，权重变化对误差的降低、提升的影响
#反向传播不断改变权重、直到误差最小化时的量被称为学习率

#学习率为一个标量参数，类似于数值积分中的步长
#用于设置调整率以更快地减小误差
#在调整权重和偏差时，学习率在反向传播中使用

#学习率越大，算法运行得越快，误差减小得越快
#训练过程也就越快

#1.13 逐步说明神经网络和激活函数
#1、将输入作为矩阵
#2、用随机值初始化权重和偏差
#3、对于每个训练模式重复4-9，直到误差最小化
#前向传播
#4、将输入应用于网络
#5、计算从输入层通过隐含层到达输出层的每个神经元的输出
#反向传播
#6、计算输出误差，即实际值减去预测值
#7、计算输出误差来计算先前层的误差信号。激活函数的偏导数用于计算误差信号
#8、使用误差信号计算权重调整值
#9、应用权重调整值

#学习率为配置参数控制权重更新的量
#完整的前向传播、后向传播为训练周期或epoch
#更新的权重在下一个周期中使用，保持迭代训练，直到误差非常小


#1.14 前馈和反馈神经网络
#前馈：仅在一个方向上
#反馈：具有某种内部循环
#添加循环是为了产生动态行为，特别是在解决涉及时间序列的问题时

#1.15 梯度下降
#任何学习模型中用于纠错的迭代方法
#对于反向传播过程中的神经网络，
#梯度下降法根据激活函数的误差迭代权重和偏差的更新过程
#最深的下降步长由前一步的相似步长代替

#梯度基本上定义为曲线的斜率，是激活函数的导数

#目的是找到全局最小成本，此时误差最小

#可以全批量或随机进行梯度下降
#随机梯度下降（SGD）的优势在于更快地计算梯度

#1.16 神经网络分类法
#1、自适应线性元件(Adaptive Linear Element, ADALINE)是一种简单的感知机，
#只能解决线性问题，每个神经元获取输入的加权线性和
#2、多重ADALINE
#3、感知机是单层神经网络，输入多维向量，输出为输入的加权和的函数
#4、径向基函数网络
#5、前馈神经网络：自编码神经网络、概率神经网络、时延神经网络、卷积神经网络
#6、循环神经网络：Hopfield神经网络、
#波尔兹曼机(Boltzmann machine)
#自组织映射(Self Organizing Map, SOM)
#双向联想映射(Bidirectional Associate Memory, BAM)
#长短期记忆(Long Short Term Memory, LSTM)


#1.17 使用R语言神经网络添加包neuralnet的简单示例
#加载包
library(neuralnet)

#设定工作目录
setwd("C:\\Users\\lenovo\\Desktop\\R\\神经网络_R语言实现\\Chapter1")
getwd()

#读取文件
mydata <- read.csv("Squares.csv", sep = ",", header = TRUE)
mydata
attach(mydata)
names(mydata)

#模型训练
model <- neuralnet(formula = Output~Input,
                   data = mydata,
                   hidden = 10,
                   threshold = 0.01)
print(model)

#展示模型
plot(model)

#检查数据的误差
final_output <- cbind(Input, Output,
                      as.data.frame(model$net.result))
colnames(final_output) = c("Input", "Expected Output",
                           "Neural Net Output")
print(final_output)

#1.18 使用添加包nnet进行实现
#3个输入与1个输出的分类问题
#包加载
#install.packages("NeuralNetTools")
library(NeuralNetTools)
library(nnet)

#设定工作目录
setwd("C:\\Users\\lenovo\\Desktop\\R\\神经网络_R语言实现\\Chapter1")
getwd()

#数据读入
mydata <- read.csv('RestaurantTips.csv', sep = ",", header = TRUE)
mydata
attach(mydata)
names(mydata)

#模型训练
model <- nnet(CustomerWillTip~Service+Ambience+Food,
              data = mydata,
              size = 5,
              rang = 0.1,
              dacay = 5e-2,
              maxit = 5000
              )
print(model)
#绘制模型
plotnet(model)
#获得神经网络中的输入变量的相对重要性
garson(model)
#可见，服务态度对给小费的决定影响较大

#1.19 深度学习
#具有许多隐含层的神经网络

#1.20 神经网络的优缺点

#1.21 神经网络实现的最佳实践
#有良好的训练数据
#MLP中隐含层越多，预测模型的准确性越好
#隐含层最好有5个节点
#ReLU和误差平方和（SSE）分别是激活函数和误差检测的最佳技术
#1.22 有关GPU处理的简要说明
#GPU是专门用于执行图形操作（例如游戏、3D动画等）的专用处理器
#它们执行数学密集型任务，是CPU的附加功能